/*
 * 栈的顺序存储
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>




#define MinStackSize 10



/* type */
struct Student {
    int id;
    char name[100];
    int age;
    char sex;
};
typedef struct Student ElemType;
//typedef int ElemType;


/*
 *
 */
struct node {
    ElemType *data;
    int size;
    int top;
};
typedef struct node stack_t;



stack_t *
init_stack(int size)
{
    stack_t *s = NULL;

    if (size < MinStackSize)
        size = MinStackSize;

    s = malloc(sizeof(stack_t));
    if (s == NULL)
        return NULL;

    s->data = malloc(sizeof(ElemType) * size);
    if (s->data == NULL)
        return NULL;
    s->size = size;
    s->top = -1;

    return s;
}



void
clear_stack(stack_t *s)
{
    if (s != NULL) {
        free(s->data);
        free(s);
        s = NULL;
    }
}

int
get_stack_length(stack_t *stack)
{
    return stack->top + 1;
}


int
is_stack_empty(stack_t *stack)
{
    return stack->top == -1;
}

int
is_stack_full(stack_t *stack)
{
    return (stack->top + 1 >= stack->size);
}


int
push(stack_t *stack, ElemType *item)
{
    /* if full */
    if (stack->top == stack->size - 1)
        return -1;

    /* point to the next empty position */
    stack->data[++stack->top] = *item;

    return 0;
}



int
pop(stack_t *stack, ElemType *item)
{
    /* if empty */
    if (stack->top == -1)
        return -1;

    *item = stack->data[stack->top--];

    return 0;
}

int
get_stack_top_item(stack_t *stack, ElemType *item)
{
    if (stack->top == -1)
        return -1;

    *item = stack->data[stack->top];

    return 0;
}





/******************************************************************************/


int
main(void)
{
    stack_t *stack;
    int i, ret;
    ElemType item;

    stack = init_stack(20);
    if (stack == NULL)
        return -1;



    printf("After init, length = %d\n", get_stack_length(stack));
    printf("After init, is_stack_empty = %d\n", is_stack_empty(stack));


    /* 插入10个节点 */
    for (i = 0; i < 15; ++i) {
        memset(&item, 0, sizeof(item));
        item.id = i+1;
        snprintf(item.name, sizeof(item.name), "Stu_%02d", item.id);
        printf("push() item[%d] ret[%d]\n", i, push(stack, &item));
    }
    printf("\n");
    printf("After push, length = %d\n", get_stack_length(stack));
    printf("After push, is_stack_empty = %d\n", is_stack_empty(stack));



    memset(&item, 0, sizeof(item));
    get_stack_top_item(stack, &item);
    printf("After push, top item: Stu_id[%d], Stu_Name[%s]\n", item.id, item.name);


    printf("\n");
    /* 弹出10个节点 */
    for (i = 0; i < 15; ++i) {
        memset(&item, 0, sizeof(item));
        ret = pop(stack, &item);
        printf("pop() item[%d] ret[%d]\n", i, ret);
        if (ret == 0)
            printf("-- Stu_id[%d], Stu_Name[%s]\n", item.id, item.name);
    }
    printf("After pop, length = %d\n", get_stack_length(stack));
    printf("After pop, is_stack_empty = %d\n", is_stack_empty(stack));


    clear_stack(stack);
    stack = NULL;
    //clear_stack(stack);
    //clear_stack(stack);

    /* 需要重新初始化 */
    stack = init_stack(5);
    if (stack == NULL)
        return -1;



    printf("\n");
    printf("After clear, length = %d\n", get_stack_length(stack));
    printf("After clear, is_stack_empty = %d\n", is_stack_empty(stack));


    /* 插入5个节点 */
    for (i = 0; i < 5; ++i) {
        memset(&item, 0, sizeof(item));
        item.id = i+1;
        snprintf(item.name, sizeof(item.name), "Stu_%02d", item.id);
        printf("push() item[%d] ret[%d]\n", i, push(stack, &item));
    }
    printf("\n");
    printf("After push, length = %d\n", get_stack_length(stack));
    printf("After push, is_stack_empty = %d\n", is_stack_empty(stack));

    memset(&item, 0, sizeof(item));
    get_stack_top_item(stack, &item);
    printf("After push, top item: Stu_id[%d], Stu_Name[%s]\n", item.id, item.name);


    while ((pop(stack, &item)) != -1)
        printf("pop(): Stu_id[%d], Stu_Name[%s]\n", item.id, item.name);
    printf("After pop, length = %d\n", get_stack_length(stack));
    printf("After pop, is_stack_empty = %d\n", is_stack_empty(stack));


    return 0;
}



